package remoto;

import interfaz.InterfazRemota;

import java.io.File;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import juani.CondicionDeCompra;
import juani.Item;
import modelo.AdministradorCasaCentral;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import servidor.Cliente;
import servidor.Proveedor;
import App.LeerPedido;
import App.LeerSolicitudCotizacion;
import App.LeerXML;
import VO.ConstruirCotizacion;
import VO.ConstruirFactura;
import beans.ClienteBean;
import beans.CondicionCompraBean;
import beans.DomicilioBean;
import beans.ProveedorBean;
import entity.ClienteEntity;
import entity.CondicionCompraEntity;
import entity.CotizacionEntity;
import entity.DomicilioEntity;
import entity.FacturaEntity;
import entity.ItemEntity;
import entity.ItemListado;
import entity.ListadoPecioEntity;
import entity.OrdenCompraEntity;
import entity.OrdenPedidoEntity;
import entity.ProveedorEntity;
import entity.RemitoEntity;
import entity.RodamientoEntity;
import entity.SolicitudCotizacionEntity;

public class CasaCentral extends UnicastRemoteObject implements InterfazRemota {

	private static final long serialVersionUID = 1L;
	@SuppressWarnings("unused")
	private Vector<Cliente> clientes;
	private Vector<Proveedor> proveedores;
	private AdministradorCasaCentral admin;

	public CasaCentral() throws RemoteException {
		clientes = new Vector<Cliente>();
		setProveedores(new Vector<Proveedor>());
		admin = new AdministradorCasaCentral();
		
//		this.recibirSolicitudCotizacion();
//		this.recibirPedido();
	}

	@Override
	public Set<String> recuperarListados() throws RemoteException {
		return admin.recuperarPrecios();
	}

	@Override
	public boolean ingresarCliente(ClienteBean cliente) throws RemoteException {
		DomicilioBean db = cliente.getDomicilio();
		DomicilioEntity de = new DomicilioEntity(db.getCalle(), db.getNumero(),
				db.getPiso(), db.getDepartamento(), db.getLocalidad());
		List<CondicionCompraBean> con = cliente.getCondicionesCompra();
		List<CondicionCompraEntity> conEntity = this.pasarDeBeanAEntity(con);
		ClienteEntity ce = new ClienteEntity(cliente.getCuit(),
				cliente.getNombre(), cliente.getCondicionIva(), conEntity, de);
		admin.ingresarCliente(ce);
		return true;
	}

	public List<CondicionCompraEntity> pasarDeBeanAEntity(
			List<CondicionCompraBean> condiciones) {
		List<CondicionCompraEntity> resultado = new ArrayList<CondicionCompraEntity>();
		for (int i = 0; i < condiciones.size(); i++) {
			CondicionCompraBean c = condiciones.get(i);
			CondicionCompraEntity cE = new CondicionCompraEntity(
					c.getFormaDePago(), c.getPlazo(), c.getIntereses(),
					c.getDescuentos());
			cE.setIdCondicion(c.getId());
			resultado.add(cE);
		}
		return resultado;
	}

	@Override
	public List<ClienteBean> obtenerClientes() throws RemoteException {
		List<ClienteEntity> clientes = admin.obtenerClientes();
		List<ClienteBean> resultado = this.pasarDeBeanAEntityCliente(clientes);
		return resultado;

	}

	private List<ClienteBean> pasarDeBeanAEntityCliente(
			List<ClienteEntity> clientes2) {
		List<ClienteBean> clientes = new ArrayList<ClienteBean>();
		for (int i = 0; i < clientes2.size(); i++) {
			if (clientes2.get(i).isEstado()) {
				ClienteEntity ce = clientes2.get(i);
				List<CondicionCompraEntity> condicionesEntity = ce
						.getCondicionCompra();
				List<CondicionCompraBean> condicionesbean = new ArrayList<CondicionCompraBean>();
				for (int j = 0; j < condicionesEntity.size(); j++) {
					CondicionCompraEntity condion = condicionesEntity.get(j);
					CondicionCompraBean condBean = new CondicionCompraBean(
							condion.getFormaDePago(), condion.getPlazo(),
							condion.getIntereses(), condion.getDescuentos());
					condBean.setId(condion.getIdCondicion());
					condicionesbean.add(condBean);
				}
				DomicilioEntity dom = ce.getDomicilio();
				DomicilioBean domBean = new DomicilioBean(dom.getCalle(),
						dom.getNumero(), dom.getPiso(), dom.getDepartamento(),
						dom.getLocalidad());
				ClienteBean cliente = new ClienteBean(ce.getCuit(),
						ce.getNombre(), ce.getCondicionIva(), null, domBean);
				clientes.add(cliente);
			}

		}
		return clientes;
	}

	@Override
	public boolean eliminarCliente(ClienteBean cliente) throws RemoteException {
		ClienteEntity ce = new ClienteEntity();
		ce.setCuit(cliente.getCuit());
		return admin.eliminarCliente(ce);
	}

	@Override
	public List<CondicionCompraBean> obtenerCondicionCompra()
			throws RemoteException {
		List<CondicionCompraEntity> condiciones = admin
				.obtenerCondicionCompra();
		List<CondicionCompraBean> resultado = new ArrayList<CondicionCompraBean>();
		for (int i = 0; i < condiciones.size(); i++) {
			CondicionCompraEntity e = condiciones.get(i);
			CondicionCompraBean c = new CondicionCompraBean(e.getFormaDePago(),
					e.getPlazo(), e.getIntereses(), e.getDescuentos());
			c.setId(e.getIdCondicion());
			resultado.add(c);
		}
		return resultado;
	}

	@Override
	public List<CondicionCompraBean> obtenerCondicionesCompra(
			ClienteBean clienteActual) throws RemoteException {
		List<CondicionCompraEntity> cond = admin
				.obtenerCondicionesCompra(clienteActual);
		List<CondicionCompraBean> resultado = new ArrayList<CondicionCompraBean>();
		for (int i = 0; i < cond.size(); i++) {
			CondicionCompraEntity ce = cond.get(i);
			CondicionCompraBean cb = new CondicionCompraBean(
					ce.getFormaDePago(), ce.getPlazo(), ce.getIntereses(),
					ce.getDescuentos());
			resultado.add(cb);
		}
		return resultado;
	}

	
	@Override
	@SuppressWarnings("unchecked")
	public boolean ingresarProveedor(ProveedorBean proveedor)
			throws RemoteException {

		DomicilioBean db = proveedor.getDomicilio();
		DomicilioEntity de = new DomicilioEntity(db.getCalle(), db.getNumero(),
				db.getPiso(), db.getDepartamento(), db.getLocalidad());

		List<CondicionCompraBean> con = (List<CondicionCompraBean>) proveedor
				.getCondicionCompra();
		List<CondicionCompraEntity> conEntity = this.pasarDeBeanAEntity(con);
		// ProveedorEntity pe = new ProveedorEntity(proveedor.getCuit(),
		// proveedor.getNombre(), proveedor.getEstyado(),
		// conEntity, de);
		ProveedorEntity pe = new ProveedorEntity();
		admin.ingresarProveedor(pe);
		return true;
	}

	@Override
	public void enviarListadoPrecios(Document listaPrecios)
			throws RemoteException {
		LeerXML doc = new LeerXML(listaPrecios);
		String cuit = doc.getProveedor().getCuil();
		ProveedorEntity pro = admin.obtenerProveedor(cuit);
		if (pro != null) {
			List<Item> items = doc.getItemRodamiento();
			List<ItemListado> items2 = new ArrayList<ItemListado>();
			for (int i = 0; i < items.size(); i++) {
				Item it = items.get(i);
				ItemListado it2 = new ItemListado();
				String cod = String.valueOf(it.getSerie());
				RodamientoEntity rod = admin.obtenerRodamiento(cod);
				if (rod == null) {
					rod = new RodamientoEntity(String.valueOf(it.getSerie()),
							it.getSufijo(), it.getOrigen(), it.getMarca(),
							null, it.getPrecio()*this.obtenerGanancia(), pro);
				}
				it2.setCantidad(0);
				it2.setPrecio(it.getPrecio()*this.obtenerGanancia());
				it2.setRodamiento(rod);
				items2.add(it2);
			}
			ListadoPecioEntity l = new ListadoPecioEntity();
			l.setId(doc.getNroListado());
			l.setItems(items2);
			try {
				String formato = "dd-MM-yyyy";
				SimpleDateFormat sdf = new SimpleDateFormat(formato);
				Date desde = sdf.parse(doc.getVigenciaListadoPrecio()
						.getFechaDesde());
				Date hasta = sdf.parse(doc.getVigenciaListadoPrecio()
						.getFechaHasta());
				l.setValidezDesde(desde);
				l.setValidezHasta(hasta);
			} catch (Exception e) {

			}
			List<ListadoPecioEntity> listados =admin.obtenerListadosProveedor(pro.getCuit());
			listados.add(l);
			pro.setListados(listados);
			admin.vincularListadoProveedor(pro);
		}
	}

	private double obtenerGanancia() {
		return admin.obtenerGanancia();
	}

	public Document recibirSolicitudCotizacion(Document cotizacion) {
		SolicitudCotizacionEntity soli = null;
		try {
			DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
			Document solicitud = docBuilder.parse(new File(
					"solicitudCotizacion2.xml"));
			LeerSolicitudCotizacion s = new LeerSolicitudCotizacion(solicitud);
			soli = new SolicitudCotizacionEntity();
			soli.setNumero(s.getNroSolicitud());
			List<Item> li = s.getRodamientos();
			System.out.println("Casa central");
			List<ItemEntity> lis = new ArrayList<ItemEntity>();
			for (int i = 0; i < li.size(); i++) {
				Item it = li.get(i);
				RodamientoEntity rod = this.obtenerMejorRodamiento(String.valueOf(it.getSerie()),it.getCantidad());
				if (rod != null) {
					ItemEntity it2 = new ItemEntity();
					it2.setRodamiento(rod);
					it2.setCantidad(0);
					it2.setPrecio(rod.getPrecio());
					it2.setCantidad(it.getCantidad());
					lis.add(it2);
				}
			}
			ClienteEntity c = admin.obtenerCliente(s.getCliente().getCuil());
			soli.setCliente(c);
			soli.setItems(lis);
			soli.setFecha(new Date());
			admin.guardarSolicitudCotizacion(soli);
		} catch (Exception e) {

		}
		try {
			System.out.println("Casa central 1");
			return (this.pasarSolicitudXML(soli));
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("Casa central2");
		return null;
	}

	private Document pasarSolicitudXML(SolicitudCotizacionEntity soli) throws ParserConfigurationException, SAXException {
		CotizacionEntity cot=new CotizacionEntity();
		cot.setCliente(soli.getCliente());
		List<CondicionCompraEntity> condiciones=this.obtenerCondicionesCompra(soli.getCliente());
		cot.setCondicionCompra(condiciones);
		cot.setEstado("Activa");
		cot.setFecha(soli.getFecha());
		Date vencimiento=soli.getFecha();
		vencimiento.setDate(vencimiento.getDate()+30);
		cot.setFechaVencimiento(vencimiento);
		cot.setItems(soli.getItems());
		cot.setNumero(soli.getNumero());
		cot.calcularIva();
		cot.calcularTotal();
		admin.guardarCotizacion(cot);
		System.out.println("Casa central3");
		ConstruirCotizacion coti=new ConstruirCotizacion(cot);
		
		return coti.generarXML();
	}

	private List<CondicionCompraEntity> obtenerCondicionesCompra(
			ClienteEntity cliente) {
		return admin.obtenerCondicionesCompraCliente(cliente);
	}

	private RodamientoEntity obtenerMejorRodamiento(String codigo,int stock) {
		List<RodamientoEntity> rods = admin.obtenerRodamientos(codigo);
		RodamientoEntity r = new RodamientoEntity();
		r.setPrecio(0);
		for (int i = 0; i < rods.size(); i++) {
			RodamientoEntity ro = rods.get(i);
			if(ro.getStock()!=null){
				if(ro.getStock().getStock()>=stock){
					if (r.getPrecio() == 0 || ro.getPrecio() < r.getPrecio()) {
						r = ro;
					}
				}else{
					r=this.obtenerRodamientoListado(codigo);
				}
			}else{
				r=this.obtenerRodamientoListado(codigo);	
			}
			
		}
		return r;
	}
	private RodamientoEntity obtenerRodamientoListado(String codigo){
		List<ListadoPecioEntity> listado=admin.obtenerListado();
		RodamientoEntity r = new RodamientoEntity();
		r.setPrecio(0);
		for(int i=0;i<listado.size();i++){
			ListadoPecioEntity l=listado.get(i);
			if(l.getValidezHasta().after(new Date())&& l.getValidezDesde().before(new Date())){
				List<ItemListado> items=l.getItems();
				for(int j=0;j<items.size();j++){
					ItemListado it=items.get(j);
					if(it.getRodamiento().getCodigo().equals(codigo)){
						RodamientoEntity ro =it.getRodamiento(); 
						if (r.getPrecio() == 0 || it.getPrecio() < r.getPrecio()) {
							r = ro;
							r.setPrecio(it.getPrecio());
						}
						
					}
				}
			}
		}
		return r;
	}

	public Vector<Proveedor> getProveedores() {
		return proveedores;
	}

	public void setProveedores(Vector<Proveedor> proveedores) {
		this.proveedores = proveedores;
	}
	public Document recibirPedido() {
		OrdenPedidoEntity pedido = null;
		try {
			DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
			Document ped = docBuilder.parse(new File(
					"ordenPedido.xml"));
			LeerPedido s = new LeerPedido(ped);
			pedido = new OrdenPedidoEntity();
			pedido.setNumero(s.getNroSolicitud());
			List<ItemEntity> its=new ArrayList<ItemEntity>();
			List<Integer> numerosCotizaciones=s.getNumerosCotizaciones();
			List<CotizacionEntity> cotizaciones=new ArrayList<CotizacionEntity>();
			for(int i=0;i<numerosCotizaciones.size();i++){
				List<ItemEntity> items=new ArrayList<ItemEntity>();
				if(this.cotizacionValida(numerosCotizaciones.get(i))){
					cotizaciones.add(this.obtenerCotizacion(numerosCotizaciones.get(i)));
					items=this.obtenerItemsCotizacion(numerosCotizaciones.get(i));
					its.addAll(items);
				}
			}
			pedido.setCotizaciones(cotizaciones);
			for(int i=0;i<its.size();i++){
				its.get(i).setId(0);
			}
			pedido.setItems(its);
			CondicionDeCompra c=s.getCondicionCompra();
			CondicionCompraEntity cond=this.buscarCondicionCompra(c.getFormaPago());
			pedido.setCondicionCompra(cond);
			String[]fechas=s.getFecha().split("-");
			Date fecha=new Date();
			fecha.setDate(Integer.valueOf(fechas[0]));
			fecha.setMonth(Integer.valueOf(fechas[1]));
			fecha.setYear(Integer.valueOf(fechas[2]));
			pedido.setFecha(fecha);
			int numero=this.obtenerNumeroPedido();
			if(numero==-1){
				numero=1;
			}
			pedido.setNumero(numero);
			ClienteEntity cl=this.obtenerCliente(s.getCliente().getCuil());
			pedido.setCliente(cl);
			pedido.calcularTotal();
			admin.guardarPedido(pedido);
		} catch (Exception e) {

		}
		return (this.pasarPedidoXML(pedido));
	}

	private CondicionCompraEntity buscarCondicionCompra(String formaPago) {
		return admin.buscarCondicionCompra(formaPago);
	}

	private ClienteEntity obtenerCliente(String cuit) {
		return admin.obtenerCliente(cuit);
	}

	private Document pasarPedidoXML(OrdenPedidoEntity pedido) {
		RemitoEntity remito=new RemitoEntity();
		if(pedido.getCotizaciones().isEmpty()){
			System.out.println("No hay cotizaciones - Es un error que vino en el ultimo commit.!!!");
			return null;
		}
		else{
		remito.setCliente(pedido.getCotizaciones().get(0).getCliente());
		remito.setFecha(new Date());
		int numero=this.obtenerNumeroRemito();
		if(numero==-1){
			numero=1;
		}
		remito.setNumero(numero);
		remito.setOrden(this.obtenerOrdenPedido(pedido.getNumero()));
		remito.setItems(pedido.getItems());
		admin.guardarRemito(remito);
		return (this.guardarFactura(remito));
		}
	}

	private OrdenPedidoEntity obtenerOrdenPedido(int numero) {
		return admin.obtenerOrdenPedido(numero);
	}

	private Document guardarFactura(RemitoEntity remito) {
		FacturaEntity factura=new FacturaEntity();
		factura.setCliente(remito.getCliente());
		factura.setFecha(new Date());
		factura.setFormaDePago(remito.getOrden().getCondicionCompra().getFormaDePago());
		factura.setItems(remito.getItems());	
		int numero=this.obtenerNumeroFactura();
		if(numero==-1){
			numero=1;
		}
		factura.setNumero(numero);
		factura.setOrdenPedido(this.obtenerOrdenPedido(remito.getOrden().getNumero()));
		factura.calcularImportes();
		admin.guardarFactura(factura);
		this.verificarDisponibilidad(factura);
		try{
			return generarXMLFactura(factura);
		}catch(Exception e){
			
		}
		return null;
	}

	private void verificarDisponibilidad(FacturaEntity factura) {
		List<ItemEntity> itemsOrdenC=factura.getItems();
		List<ItemEntity> its=new ArrayList<ItemEntity>();
		for(int i=0;i<itemsOrdenC.size()&&itemsOrdenC.size()!=its.size();i++){
			OrdenCompraEntity or=new OrdenCompraEntity();
			List<ItemEntity> aux=itemsOrdenC;
			its=new ArrayList<ItemEntity>();
			for(int j=0;j<aux.size();j++){
				RodamientoEntity rod=aux.get(i).getRodamiento();
				ItemEntity it=new ItemEntity();
				if(its.size()>0){
					if(rod.getProveedor().getCuit().equals(or.getProveedor().getCuit())){
						it=aux.get(i);
					}
				}else{
					it=aux.get(i);
					or.setProveedor(it.getRodamiento().getProveedor());
				}
				its.add(it);
			}
			or.setFecha(new Date());
			or.setItems(its);
			or.setNumero(this.obtenerNumeroOrdenCompra());//obtener Numero
			or.calcularImportes();
			admin.guardarOrdenCompra(or);
		}
		
	}

	private int obtenerNumeroOrdenCompra() {
		int numero=admin.obtenerNUmeroOrdenCompra();
		if(numero==-1){
			numero=1;
		}
		return numero;
	}

	private Document generarXMLFactura(FacturaEntity factura) {
		ConstruirFactura cons=new ConstruirFactura(factura);
		try {
			cons.generarXML();
		} catch (ParserConfigurationException e) {
		} catch (SAXException e) {
		}
		return null;
		
	}

	private int obtenerNumeroFactura() {
		return admin.obtenerNumeroFactura();
	}

	private int obtenerNumeroRemito() {
		return admin.obtenerNumeroRemito();
	}

	private int obtenerNumeroPedido() {
		return admin.obtenerNumeroPedido();
	}

	private List<ItemEntity> obtenerItemsCotizacion(int numero) {
		return admin.obtenerItemsCotizacion(numero);
	}

	private CotizacionEntity obtenerCotizacion(int numero) {
		return admin.obtenerCotizacion(numero);
	}

	private boolean cotizacionValida(int numero) {
		Date fecha= admin.cotizacionValida(numero);
		Date actual=new Date();
		if(fecha!=null){
			if(actual.getYear()<=fecha.getYear()){
				if(actual.getMonth()<=fecha.getMonth()){
					if(actual.getDate()<=fecha.getDate()){
						return true;
					}else{
						if(actual.getMonth()<fecha.getMonth() && actual.getDate()>=fecha.getDate()){
							return true;
						}
					}
				}else{
					if(actual.getYear()<fecha.getYear() && actual.getMonth()>=fecha.getDate()){
						return true;
					}
				}
			}
		}
		return false;
	}

	@Override
	public ClienteBean obtenerCliente2(String cuit) throws RemoteException {
		ClienteEntity c= admin.obtenerCliente(cuit);
		List<ClienteEntity> cl=new ArrayList<ClienteEntity>();
		cl.add(c);
		ClienteBean cliente = this.pasarDeBeanAEntityCliente(cl).get(0);
		return cliente;
	}

	@Override
	public String[] obtenerRodamientos() throws RemoteException {
		// TODO Auto-generated method stub
		return null;
	}

}
